local class = reload("class")
local super = reload("super.database")
local mysqlC = require("mysqlC")
local treply = {
    select = 1,
    selectMap = 2,
    showTableList = 3,       ---获取表列表
    showCreateTable = 4,     ---获取表创建语句
    showTableColumn = 5,     ---获取表字段
    showTableIndex = 6,      ---获取表索引
    showProcedureList = 7,   ---获取存储过程列表
    showCreateProcedure = 8, ---获取存储过程创建语句
}
---@class mysqlLC : database
local this = class(super)

function this:ctor(name, info)
    super.ctor(self)
    self._name = name
    self._info = info
end

function this:launch()
    local info = self._info
    mysqlC.new(
        self._name,
        info.ip,
        info.port,
        info.db,
        info.charset,
        info.user,
        info.password,
        self)
    return self:hand()
end

function this:callback(cookid)
    ---标记需要回调
    mysqlC.callback(cookid)
end

function this:decode(ireply, info, ...)
    if ireply == treply.select then
        self:selectpush(info.args, ...)
    elseif ireply == treply.selectMap then
        self:selectMapPush(info.args, ...)
    elseif ireply == treply.showTableList then
        self:showTablesPush(info.args, ...)
    elseif ireply == treply.showCreateTable then
        self:showCreateTablePush(info.args, ...)
    elseif ireply == treply.showTableColumn then
        self:showTableColumnPush(info.args, ...)
    elseif ireply == treply.showTableIndex then
        self:showTableIndexPush(info.args, ...)
    elseif ireply == treply.showProcedureList then
        self:showProcedureListPush(info.args, ...)
    elseif ireply == treply.showCreateProcedure then
        self:showCreateProcedurePush(info.args, ...)
    end
end

function this:insert(sql, ...)
    assert(self._info.write or false, "没有写入权限")
    local cookid = self:cook()
    mysqlC.insert(cookid, self._name, sql, ...)
    return self:watch(false)
end

function this:update(sql, ...)
    assert(self._info.write or false, "没有写入权限")
    local cookid = self:cook()
    mysqlC.update(cookid, self._name, sql, ...)
    return self:watch(false)
end

function this:delete(sql)
    assert(self._info.write or false, "没有写入权限")
    local cookid = self:cook()
    mysqlC.delete(cookid, self._name, sql)
    return self:watch(false)
end

function this:select(sql)
    local cookid = self:cook()
    mysqlC.select(cookid, self._name, sql)
    return self:watch(treply.select)
end

function this:selectTableComment()
    local fmt = [[select table_name,table_comment from information_schema.TABLES where table_schema = '%s';]]
    local cookid = self:cook()
    mysqlC.select(cookid, self._name, fmt:format(self._info.db))
    return self:watch(treply.selectMap)
end

function this:create(sql)
    assert(self._info.write or false, "没有写入权限")
    local cookid = self:cook()
    mysqlC.create(cookid, self._name, sql)
    return self:watch(false)
end

function this:drop(sql)
    assert(self._info.write or false, "没有写入权限")
    local cookid = self:cook()
    mysqlC.drop(cookid, self._name, sql)
    return self:watch(false)
end

function this:dropTable(tbname)
    local sql = string.format("drop table `%s`;", tbname)
    return self:drop(sql)
end

function this:dropProcedure(procName)
    local sql = string.format("drop procedure `%s`;", procName)
    return self:drop(sql)
end

function this:alter(sql)
    assert(self._info.write or false, "没有写入权限")
    local cookid = self:cook()
    mysqlC.alter(cookid, self._name, sql)
    return self:watch(false)
end

function this:truncate(sql)
    assert(self._info.write or false, "没有写入权限")
    local cookid = self:cook()
    mysqlC.truncate(cookid, self._name, sql)
    return self:watch(false)
end

function this:explain(sql)
    assert(self._info.write or false, "没有写入权限")
    local cookid = self:cook()
    mysqlC.explain(cookid, self._name, sql)
    return self:watch(false)
end

function this:show(sql)
    local cookid = self:cook()
    mysqlC.show(cookid, self._name, sql)
    return self:watch(treply.select)
end

---获取table列表
function this:showTableList()
    local cookid = self:cook()
    mysqlC.show(cookid, self._name, "show tables;")
    return self:watch(treply.showTableList)
end

---获取table创建语句
function this:showCreateTable(tbname)
    local cookid = self:cook()
    local sql = string.format("show create table `%s`;", tbname)
    mysqlC.show(cookid, self._name, sql)
    return self:watch(treply.showCreateTable)
end

---获取table字段信息
function this:showTableColumn(tbname)
    local cookid = self:cook()
    local sql = string.format("show full columns from `%s`;", tbname)
    mysqlC.show(cookid, self._name, sql)
    return self:watch(treply.showTableColumn)
end

---获取table索引信息
function this:showTableIndex(tbname)
    local cookid = self:cook()
    local sql = string.format("show index from `%s`;", tbname)
    mysqlC.show(cookid, self._name, sql)
    return self:watch(treply.showTableIndex)
end

---获取存储过程列表
function this:showProcedureList()
    local cookid = self:cook()
    local sql = string.format("show procedure status where DB='%s';", self._info.db)
    mysqlC.show(cookid, self._name, sql)
    return self:watch(treply.showProcedureList)
end

---获取存储过程语句
function this:showCreateProcedure(procname)
    local cookid = self:cook()
    local sql = string.format("show create procedure `%s`;", procname)
    mysqlC.show(cookid, self._name, sql)
    return self:watch(treply.showCreateProcedure)
end

---读取函数列表
function this:showFunctionList()
    local cookid = self:cook()
    local sql = string.format("show function status where DB='%s';", self._info.db)
    mysqlC.show(cookid, self._name, sql)
    return self:watch(treply.showProcedureList)
end

---获取函数语句
function this:showCreateFunction(funcname)
    local cookid = self:cook()
    local sql = string.format("show create function `%s`;", funcname)
    mysqlC.show(cookid, self._name, sql)
    return self:watch(treply.showCreateProcedure)
end

function this:set(sql)
    assert(self._info.write or false, "没有写入权限")
    local cookid = self:cook()
    mysqlC.set(cookid, self._name, sql)
    return self:watch(false)
end

function this:use(sql)
    local cookid = self:cook()
    mysqlC.use(cookid, self._name, sql)
    return self:watch(false)
end

function this:await(carg)
    local sql = "show databases;"
    self:show(sql)(self.coback, self, carg)
    super.await(self, carg)
end

return this
